/* @flow */
/**
 * 作用说明(运行时)：
 * 1、设置平台化的 Vue.config
 * 2、在 Vue.options 上混合了两个指令(directives)，分别是 model 和 show
 * 3、在 Vue.options 上混合了两个组件(components)，分别是 Transition 和 TransitionGroup
 * 4、在 Vue.prototype 上添加了两个方法：__patch__ 和 $mount
 * 最后将包装后的Vue导出。供entry-runtime.js调用
 */
import Vue from 'core/index'
import config from 'core/config'
import { extend, noop } from 'shared/util'
import { mountComponent } from 'core/instance/lifecycle'
import { devtools, inBrowser, isChrome } from 'core/util/index'

import {
  query,
  mustUseProp,
  isReservedTag,
  isReservedAttr,
  getTagNamespace,
  isUnknownElement
} from 'web/util/index'

import { patch } from './patch'
import platformDirectives from './directives/index'
import platformComponents from './components/index'

// 覆盖默认导出的 config 对象的属性,用于安装平台特定的工具方法
Vue.config.mustUseProp = mustUseProp
Vue.config.isReservedTag = isReservedTag
Vue.config.isReservedAttr = isReservedAttr
Vue.config.getTagNamespace = getTagNamespace
Vue.config.isUnknownElement = isUnknownElement

// 安装特定平台运行时的指令和组件
extend(Vue.options.directives, platformDirectives)
extend(Vue.options.components, platformComponents)

/**
 * 经过上面的执行，Vue.options对象变成了
 * Vue.options = {
 *   components: {
 *     KeepAlive,
 *     Transition,
 *     TransitionGroup 
 *   },
 *   directives:{
 *     model,
 *     show
 *   },
 *   filters: Object.create(null),
 *   _base: Vue 
 * }
 */


// 在 Vue.prototype 上添加 __patch__ 方法,如果是在浏览器环境中则指向patch，否则是一个空函数noop（见shared/util.js）
Vue.prototype.__patch__ = inBrowser ? patch : noop

// 在 Vue.prototype 上添加 $mount 方法
// hydrating: 用于 Virtual DOM 的补丁算法
Vue.prototype.$mount = function (
  el?: string | Element,
  hydrating?: boolean
): Component {
  // el存在且执行环境为浏览器环境
  el = el && inBrowser ? query(el) : undefined
  // 调用 mountComponent 函数完成真正的挂载工作
  return mountComponent(this, el, hydrating)
}

/**
 * vue-devtools 的全局钩子, 被包裹在 setTimeout中
 */
if (inBrowser) {
  setTimeout(() => {
    if (config.devtools) {
      if (devtools) {
        devtools.emit('init', Vue)
      } else if (
        process.env.NODE_ENV !== 'production' &&
        process.env.NODE_ENV !== 'test' &&
        isChrome
      ) {
        console[console.info ? 'info' : 'log'](
          'Download the Vue Devtools extension for a better development experience:\n' +
          'https://github.com/vuejs/vue-devtools'
        )
      }
    }
    if (process.env.NODE_ENV !== 'production' &&
      process.env.NODE_ENV !== 'test' &&
      config.productionTip !== false &&
      typeof console !== 'undefined'
    ) {
      console[console.info ? 'info' : 'log'](
        `You are running Vue in development mode.\n` +
        `Make sure to turn on production mode when deploying for production.\n` +
        `See more tips at https://vuejs.org/guide/deployment.html`
      )
    }
  }, 0)
}

export default Vue
